<?php
/*!
 * LostKids PHP Library v0.1 
 * http://huali.li/
 *
 * Copyright 2011, 
 * Written By James Pang
 *  
 * Date: 2011/2/14
 */

/**
 * <li>uid is kid's id</li>
 * <li>tag label is seeker/reporter id, means the guy who lost/found the kid</li>
 * <li>taggerId: seeker: means the kid in lost set, reporter: means the kid in
 * found set</li>
 */
class RecognizerImpl implements Recognizer
{
    private $frClient;

    public function __construct() {
    	$this->frClient = new FaceRestClient(fc_apiKey, fc_apiSecret);
    }

    public function recognize($imgUrls, $set = 'valid')
    {
        $ret = array();

        foreach ( $imgUrls as $lid => $url ) {
            $recoged = $this->frClient->faces_recognize($url, $this->getUidByTagger(
                    $set), fc_namespace);

            if($recoged == null ||$recoged->status != 'success')
            {// failed to recognize
                throw new SysException(@$recoged->error_message, $lid);
            }
            $facesCnt = count($recoged->photos[0]->tags);
            if($facesCnt != 1)
                throw new BizException(Recognizer::ERR_MULTI_FACES, $lid);

            $matched = $recoged->photos[0]->tags[0]->uids;
            foreach($matched as $match) {
            	$confidences = @$ret[$match->uid];
                $confidences[] = $match->confidence;
                $ret[$match->uid] = $confidences;
            }
        }
        foreach($ret as $uid => $confs) {
        	$ret[$uid] = $this->evalConfidence($confs);
        }

        return $ret;
    }

    protected function evalConfidence($confidences) {
    	return $this->median($confidences);
    }
    
    private function median($arr) {
        sort($arr);
        $count = count($arr); //total numbers in array
        $middleval = floor(($count-1)/2); // find the middle value, or the lowest middle value
        if($count % 2) { // odd number, middle is the median
            $median = $arr[$middleval];
        } else { // even number, calculate avg of 2 medians
            $low = $arr[$middleval];
            $high = $arr[$middleval+1];
            $median = (($low+$high)/2);
        }
        return $median;
    }

    public function train($kidId, $set, $ownerId, $imgUrls)
    {
        foreach ( $imgUrls as $lid => $imgUrl ) {
            // #detect faces
            $detected = $this->frClient->faces_detect($imgUrl);
            if($detected == null || $detected->status != 'success')
            {// not success.
                throw new SysException(@$detected->error_message, $lid);
            }
            $tags = $detected->photos[0]->tags;
            $facesCnt = count($tags);
            if($facesCnt != 1) {
                throw new BizException(Recognizer::ERR_MULTI_FACES, $lid);
            }
    
            $uid = "$kidId@". fc_namespace;
    
            // #save face tag
            $saved = $this->frClient->tags_save($tags[0]->tid, $uid, $lid, $set);
            if($saved == null || $saved->status != 'success')
            {// failed to save
                throw new SysException(@$saved->error_message, $lid);
            }
        }

        // #train face
        $trained = $this->frClient->faces_train($uid);
        if($trained == null || $trained->status != 'success')
        {// failed to train
            throw new SysException(@$trained->error_message, @$trained->error_code);
        }
    }

    /**
     * *&lt;taggerId&gt;
     */
    private function getUidByTagger($taggerId)
    {
        if($taggerId == null || $taggerId == 'all')
        {
            return null;
        }
        return "*<$taggerId>";
    }
}
?>
